// 公共函数文件
import * as net from 'net';

export enum RequestCommand {
    LOGIN = "LOGIN",
    LOGOUT = "LOGOUT",
    SAY = "SAY",
    WHISPER = "WHISPER",
}

export enum ResponseCommand {
    INVALID_COMMAND = "INVALID_COMMAND",
    REMAIN_USER = "REMAIN_USER",
    NEW_USER = "NEW_USER",
    INVALID_USERNAME = "INVALID_USERNAME",
    USERNAME_EXIST = "USERNAME_EXIST",
    USER_LOGGED_IN = "USER_LOGGED_IN",
    LOGOUT_USER = "LOGOUT_USER",
    USER_CHAT = "USER_CHAT",
    SERVER_CLOSE = "SERVER_CLOSE",
    USER_NOT_LOGIN = "USER_NOT_LOGIN",
    USER_WHISPER = "USER_WHISPER",
    USER_NOT_EXIST = "USER_NOT_EXIST",
}

export interface MessageDate<T> {
    data: T;
}

export interface RequestMessage<T> extends MessageDate<T> {
    command: RequestCommand;
}

export interface ResponseMessage<T> extends MessageDate<T> {
    command: ResponseCommand;
}

export interface user {
    name: string;
    socket: net.Socket;
    id: string;
    ip: string;
}

export interface UserChat {
    id: string;
    message: string;
}

export interface UserInfo {
    id: string;
    name: string;
    ip: string;
}

export interface whisperMessage {
    id: string;
    message: string;
}

export function logInConsole(...args: any[]) {
    console.log(">>>", ...args);
}

declare module 'net' {
    interface Socket {
        sendJSON<T>(command: ResponseCommand | RequestCommand, data: T): void;
    }
}

net.Socket.prototype.sendJSON = function <T>(command: ResponseCommand | RequestCommand, data: T) {
    const message: ResponseMessage<T> | RequestMessage<T> = { command, data }
    this.write(JSON.stringify(message));
}

export const INVALID_COMMAND_MESSAGE = JSON.stringify({ command: ResponseCommand.INVALID_COMMAND, data: null })
export const USER_NOT_LOGIN_MESSAGE = JSON.stringify({ command: ResponseCommand.USER_NOT_LOGIN, data: null })
export const INVALID_USERNAME_MESSAGE = JSON.stringify({ command: ResponseCommand.INVALID_USERNAME, data: null })
export const USERNAME_EXIST_MESSAGE = JSON.stringify({ command: ResponseCommand.USERNAME_EXIST, data: null })
export const USER_LOGGED_IN_MESSAGE = JSON.stringify({ command: ResponseCommand.USER_LOGGED_IN, data: null })
export const SERVER_CLOSE_MESSAGE = JSON.stringify({ command: ResponseCommand.SERVER_CLOSE, data: null })
export const USER_NOT_EXIST_MESSAGE = JSON.stringify({ command: ResponseCommand.USER_NOT_EXIST, data: null })

export interface SocketHandleMethodRequest {
    (socket: net.Socket, data: any): void,
    command?: RequestCommand
    onError?: boolean
    onEnd?: boolean
    onClose?: boolean
}

export interface SocketServiceHandle {
    [key: string]: SocketHandleMethodRequest
}

export function isSocketHandleMethodRequest(obj: unknown): obj is SocketHandleMethodRequest {
    if (typeof obj === 'function' && ("onError" in obj || "onEnd" in obj || "command" in obj)) {
        return true;
    }
    return false;
}

export interface ConsoleCommandData {
    command: string,
    args: string[]
    data: string
}

export function parseCommand(input: string, prefix?: null): ConsoleCommandData {
    const data: ConsoleCommandData = {
        command: '',
        args: [],
        data: ''
    }
    if (prefix) {
        if (input[0] !== prefix) {
            return data
        }
        input = input.slice(1)
        if (input[0] === ' ') {
            return data
        }
    }
    const arr = input.split(' ').filter(item => item !== '')
    data.command = arr[0].toLocaleLowerCase()
    data.args = arr.slice(1)
    data.data = input.slice(data.command.length + 1).trim()
    return data
}

export interface ConsoleHandleMethod {
    (command: ConsoleCommandData): void,
    command?: string
}

export interface ConsoleHandle {
    [key: string]: ConsoleHandleMethod
}